package client.login;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.Serializable;
import java.net.UnknownHostException;

import client.tcp.ClientTCP;

import miscellaneous.Storage;
import mockup.LoginMockup;
import mockup.Mockup;
import mockup.MockupFactory;
import mockup.MockupToData;
import mockup.UserMockup;

import data.User;

/**
 * Holds the login information.
 * 
 * @author Erik
 */

public class Login {	
	//the user login input
	private String username;
	private String password;
	private int sessionID;
	private ClientTCP socket;
	private String ip;
	private int port;

	private UserMockup user;

	//a User object is created from the server
	//based on the login information
	private User loggedInUser;

	private PropertyChangeSupport changeSupport;	

	public Login() {
		this.changeSupport = new PropertyChangeSupport(this);
	}

	/**
	 * Set the user name and password of this object.
	 * This method will notify listeners of the change.
	 * @param userName The user name
	 * @param password The password
	 */
	public void setInfo(String username, String password, String ip, int port) throws  IOException{
		this.username = username;
		this.password = password;
		this.ip = ip;
		this.port = port;

		// back door into program
		if(username.equals("gruppe2") && password.equals("aCalendar")) {
			user = new UserMockup(42, "gruppe2", System.currentTimeMillis(), "gruppe2@fellesprosjekt.no", "00000042", "P411");

			changeSupport.firePropertyChange(new PropertyChangeEvent(this, "successLogin", username, null));
			return;
		}
		else { // real login
			if(socket == null) {
				try {
					socket = new ClientTCP(this.ip, this.port);
				} catch (UnknownHostException e) {
					System.err.println("Login::setInfo: Could not find host");
					throw new IOException("Fant ikke server");
				} catch (IOException e) {
					System.err.println("Login::setInfo: Failed to initiate connection");
					throw new IOException("Klarte ikke opprette tilkobling til server");
				}
			}

			if( ! socket.isConnected()) {
				socket = null;
				System.err.println("Login: Connection to server failed");
				throw new IOException("Tilkobling feilet");
			}

			LoginMockup login = new LoginMockup(username, password);
			Serializable answer = socket.send(login);
			if(answer == null) {
				System.err.println("Login: Received null when asking for login");
				throw new IOException("Mottok ikke et svar fra server");
			}

			if(answer instanceof LoginMockup) {
				login = (LoginMockup) answer;

				if(login.getSessionId() != -1) {
					System.out.println("Loin::setInfo: Successfull login");
					this.sessionID = login.getSessionId();
					user = login.getUser();
					changeSupport.firePropertyChange(new PropertyChangeEvent(this, "successLogin", username, null));
					return;					
				}
				else {
					System.err.println("Login::setInfo: Server refused login");
					throw new IOException("Feil brukernavn/passord kombinasjon");
				}
			}
			else {
				System.err.println("Login::setInfo: Did not receive a login from server");
				throw new IOException("Mottok feil svar fra server");
			}

		}
	}

	public User getLoggedInUser() {
		return loggedInUser;
	}

	/**
	 * Adds a listener to this login.
	 * @param listener The listener to add.
	 */
	public void addPropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.addPropertyChangeListener(listener);
	}

	/**
	 * Removes a listener to this login.
	 * @param listener The listener to remove.
	 */
	public void removePropertyChangeListener(PropertyChangeListener listener) {
		changeSupport.removePropertyChangeListener(listener);
	}

	/**
	 * @return Returns the user name.
	 */
	public String getUsername() {
		if(username != null)
			return username;
		else
			return "";
	}
	/**
	 * @return Returns the password.
	 */
	public String getPassword() {
		if(password != null)
			return password;
		else
			return "";
	}

	public static void logout() {
		try {
			LoginMockup l = new LoginMockup(
					Storage.getSessionID(),
					(UserMockup)MockupFactory.getUserMockup(Storage.getloggedInUser()));
			l.setState(Mockup.LOGOUT);
			Storage.getSocket().send(l);
		} catch (Exception e) {
			//do nothing
		}
		Storage.setLogin(null);
		System.exit(0);
	}

	public int getSessionID() {
		return sessionID;
	}

	public void setSessionID(int sessionID) {
		this.sessionID = sessionID;
	}

	public ClientTCP getSocket() {
		return socket;
	}

	public UserMockup getUser() {
		return user;
	}

	public void setUser(UserMockup user) {
		this.user = user;
	}
}
